<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>设计模式-观察者模式 | 小马过河</title>
    <meta name="generator" content="VuePress 1.8.2">
    <link rel="icon" href="/img/manong.jpg">
    <script src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
    <link rel="manifest" href="/manifest.json">
    <link rel="apple-touch-icon" href="/img/mxx-152-152.png">
    <meta name="description" content="本文章主要记录设计模式中得观察者模式。">
    <meta name="keywordsv" content="设计模式 观察者模式 观察者 Observer">
    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
    <meta name="theme-color" content="#ededed">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="msapplication-TileColor" content="#000000">
    <meta name="msapplication-TileImage" content="/img/mxx-144.png">
    
    <link rel="preload" href="/assets/css/0.styles.154256f1.css" as="style"><link rel="preload" href="/assets/js/app.f1a8d465.js" as="script"><link rel="preload" href="/assets/js/2.5bab2b7d.js" as="script"><link rel="preload" href="/assets/js/19.9d056309.js" as="script"><link rel="preload" href="/assets/js/4.dca68745.js" as="script"><link rel="prefetch" href="/assets/js/10.586b05b4.js"><link rel="prefetch" href="/assets/js/100.17640669.js"><link rel="prefetch" href="/assets/js/101.9c523894.js"><link rel="prefetch" href="/assets/js/102.27347aba.js"><link rel="prefetch" href="/assets/js/103.37a029fe.js"><link rel="prefetch" href="/assets/js/104.1d8f728c.js"><link rel="prefetch" href="/assets/js/105.8081ec6e.js"><link rel="prefetch" href="/assets/js/11.28ad280e.js"><link rel="prefetch" href="/assets/js/12.5e108f27.js"><link rel="prefetch" href="/assets/js/13.3678126c.js"><link rel="prefetch" href="/assets/js/14.505a08b7.js"><link rel="prefetch" href="/assets/js/15.8f3c0c53.js"><link rel="prefetch" href="/assets/js/16.4256e6cb.js"><link rel="prefetch" href="/assets/js/17.17d3d968.js"><link rel="prefetch" href="/assets/js/18.73488ae7.js"><link rel="prefetch" href="/assets/js/20.52185694.js"><link rel="prefetch" href="/assets/js/21.3b7e8437.js"><link rel="prefetch" href="/assets/js/22.4d4d8a8b.js"><link rel="prefetch" href="/assets/js/23.dac1a360.js"><link rel="prefetch" href="/assets/js/24.798b5147.js"><link rel="prefetch" href="/assets/js/25.16d30679.js"><link rel="prefetch" href="/assets/js/26.3e5e50ab.js"><link rel="prefetch" href="/assets/js/27.99e01b84.js"><link rel="prefetch" href="/assets/js/28.86b7c539.js"><link rel="prefetch" href="/assets/js/29.ea981f89.js"><link rel="prefetch" href="/assets/js/3.c22f362a.js"><link rel="prefetch" href="/assets/js/30.6c923d43.js"><link rel="prefetch" href="/assets/js/31.df940781.js"><link rel="prefetch" href="/assets/js/32.3e5a19c7.js"><link rel="prefetch" href="/assets/js/33.0936aa71.js"><link rel="prefetch" href="/assets/js/34.566820dc.js"><link rel="prefetch" href="/assets/js/35.e263f3e4.js"><link rel="prefetch" href="/assets/js/36.32ae1d3b.js"><link rel="prefetch" href="/assets/js/37.ac0fe1ce.js"><link rel="prefetch" href="/assets/js/38.5ff1b8eb.js"><link rel="prefetch" href="/assets/js/39.da39237f.js"><link rel="prefetch" href="/assets/js/40.c92cf280.js"><link rel="prefetch" href="/assets/js/41.b2318f21.js"><link rel="prefetch" href="/assets/js/42.9e98acc0.js"><link rel="prefetch" href="/assets/js/43.6a890842.js"><link rel="prefetch" href="/assets/js/44.8c501675.js"><link rel="prefetch" href="/assets/js/45.a7b73149.js"><link rel="prefetch" href="/assets/js/46.08c4dcbb.js"><link rel="prefetch" href="/assets/js/47.0fa3a317.js"><link rel="prefetch" href="/assets/js/48.15f53959.js"><link rel="prefetch" href="/assets/js/49.f9b62975.js"><link rel="prefetch" href="/assets/js/5.49ddc4eb.js"><link rel="prefetch" href="/assets/js/50.5d678fce.js"><link rel="prefetch" href="/assets/js/51.f07100da.js"><link rel="prefetch" href="/assets/js/52.25782c95.js"><link rel="prefetch" href="/assets/js/53.1151ca9a.js"><link rel="prefetch" href="/assets/js/54.86132d90.js"><link rel="prefetch" href="/assets/js/55.5e273c50.js"><link rel="prefetch" href="/assets/js/56.94d89ae7.js"><link rel="prefetch" href="/assets/js/57.ff4f6ce5.js"><link rel="prefetch" href="/assets/js/58.d6bba7bf.js"><link rel="prefetch" href="/assets/js/59.fd39aa8f.js"><link rel="prefetch" href="/assets/js/6.73ba3b93.js"><link rel="prefetch" href="/assets/js/60.3b547209.js"><link rel="prefetch" href="/assets/js/61.c2746621.js"><link rel="prefetch" href="/assets/js/62.c7246830.js"><link rel="prefetch" href="/assets/js/63.8cf018aa.js"><link rel="prefetch" href="/assets/js/64.5982f68e.js"><link rel="prefetch" href="/assets/js/65.6a323f0b.js"><link rel="prefetch" href="/assets/js/66.df6d599d.js"><link rel="prefetch" href="/assets/js/67.5c26c24c.js"><link rel="prefetch" href="/assets/js/68.e53dceea.js"><link rel="prefetch" href="/assets/js/69.65ee4851.js"><link rel="prefetch" href="/assets/js/7.541920c5.js"><link rel="prefetch" href="/assets/js/70.4bfafea4.js"><link rel="prefetch" href="/assets/js/71.b4f496a8.js"><link rel="prefetch" href="/assets/js/72.1b1ffea6.js"><link rel="prefetch" href="/assets/js/73.8929e1c4.js"><link rel="prefetch" href="/assets/js/74.d3c5fcad.js"><link rel="prefetch" href="/assets/js/75.9d01a456.js"><link rel="prefetch" href="/assets/js/76.3149b796.js"><link rel="prefetch" href="/assets/js/77.3abe6bd4.js"><link rel="prefetch" href="/assets/js/78.ae477312.js"><link rel="prefetch" href="/assets/js/79.00837d52.js"><link rel="prefetch" href="/assets/js/8.a50175f7.js"><link rel="prefetch" href="/assets/js/80.d626622b.js"><link rel="prefetch" href="/assets/js/81.ad2df06d.js"><link rel="prefetch" href="/assets/js/82.9ac0d88a.js"><link rel="prefetch" href="/assets/js/83.b23219b4.js"><link rel="prefetch" href="/assets/js/84.55f2741f.js"><link rel="prefetch" href="/assets/js/85.33b715e5.js"><link rel="prefetch" href="/assets/js/86.85aea4fa.js"><link rel="prefetch" href="/assets/js/87.6fd2f3fa.js"><link rel="prefetch" href="/assets/js/88.a9ea00b4.js"><link rel="prefetch" href="/assets/js/89.7e58e472.js"><link rel="prefetch" href="/assets/js/9.83acbe8c.js"><link rel="prefetch" href="/assets/js/90.e15687d5.js"><link rel="prefetch" href="/assets/js/91.026b108a.js"><link rel="prefetch" href="/assets/js/92.840afd12.js"><link rel="prefetch" href="/assets/js/93.00439ef2.js"><link rel="prefetch" href="/assets/js/94.6c994a63.js"><link rel="prefetch" href="/assets/js/95.e3dd6367.js"><link rel="prefetch" href="/assets/js/96.cbe1207c.js"><link rel="prefetch" href="/assets/js/97.34584059.js"><link rel="prefetch" href="/assets/js/98.9b2de21d.js"><link rel="prefetch" href="/assets/js/99.95d4993f.js">
    <link rel="stylesheet" href="/assets/css/0.styles.154256f1.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="layout-wrapper"><!----> <div class="theme-container"><header class="navbar ele-navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/img/manong.jpg" alt="小马过河" class="logo"> <span class="site-name can-hide">小马过河</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><!----> <a href="/" class="nav-link">
  首页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="导航" class="dropdown-title"><span class="title">导航</span> <span class="arrow down"></span></button> <button type="button" aria-label="导航" class="mobile-dropdown-title"><span class="title">导航</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/nav/nav.html" class="nav-link">
  常用站点
</a></li><li class="dropdown-item"><!----> <a href="/nav/web.html" class="nav-link">
  前端站点
</a></li><li class="dropdown-item"><!----> <a href="/nav/afterEnd.html" class="nav-link">
  后端站点
</a></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端" class="dropdown-title"><span class="title">前端</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端" class="mobile-dropdown-title"><span class="title">前端</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          CSS+HTML系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/web/csshtml/css-formatContent.html" class="nav-link">
  CSS格式化上下文
</a></li><li class="dropdown-subitem"><a href="/web/csshtml/css-bfc.html" class="nav-link">
  CSS的BFC
</a></li></ul></li><li class="dropdown-item"><h4>
          JS系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/web/js/js-prototype.html" class="nav-link">
  JS-原型与原型链
</a></li><li class="dropdown-subitem"><a href="/web/js/js-context.html" class="nav-link">
  JS-执行上下文
</a></li></ul></li><li class="dropdown-item"><h4>
          Vue2系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/web/vue/mvvm.html" class="nav-link">
  Vue响应式
</a></li></ul></li><li class="dropdown-item"><h4>
          常见面试题
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/web/question/css.html" class="nav-link">
  CSS面试题
</a></li><li class="dropdown-subitem"><a href="/web/question/vue.html" class="nav-link">
  Vue2.x面试题
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Java" class="dropdown-title"><span class="title">Java</span> <span class="arrow down"></span></button> <button type="button" aria-label="Java" class="mobile-dropdown-title"><span class="title">Java</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          基础系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/basics/know.html" class="nav-link">
  Java初识
</a></li><li class="dropdown-subitem"><a href="/java/basics/number.html" class="nav-link">
  Java数字
</a></li><li class="dropdown-subitem"><a href="/java/basics/string.html" class="nav-link">
  Java字符串
</a></li></ul></li><li class="dropdown-item"><h4>
          集合
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/collection/collection.html" class="nav-link">
  Collection集合
</a></li><li class="dropdown-subitem"><a href="/java/collection/list.html" class="nav-link">
  List集合
</a></li></ul></li><li class="dropdown-item"><h4>
          IO操作
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/io/" class="nav-link">
  IO初识
</a></li></ul></li><li class="dropdown-item"><h4>
          网络编程
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/network/ip.html" class="nav-link">
  IP操作
</a></li></ul></li><li class="dropdown-item"><h4>
          JDBC操作
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/jdbc/mysql-connect.html" class="nav-link">
  MySQL操作
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="数据库" class="dropdown-title"><span class="title">数据库</span> <span class="arrow down"></span></button> <button type="button" aria-label="数据库" class="mobile-dropdown-title"><span class="title">数据库</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          MySQL系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/database/mysql/init.html" class="nav-link">
  常用语法
</a></li><li class="dropdown-subitem"><a href="/database/mysql/data-type.html" class="nav-link">
  数据类型
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="设计模式" class="dropdown-title"><span class="title">设计模式</span> <span class="arrow down"></span></button> <button type="button" aria-label="设计模式" class="mobile-dropdown-title"><span class="title">设计模式</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/designMode/observer.html" aria-current="page" class="nav-link router-link-exact-active router-link-active">
  观察者模式
</a></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="运维/工具" class="dropdown-title"><span class="title">运维/工具</span> <span class="arrow down"></span></button> <button type="button" aria-label="运维/工具" class="mobile-dropdown-title"><span class="title">运维/工具</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Maven
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/tools/maven/" class="nav-link">
  初识
</a></li></ul></li><li class="dropdown-item"><h4>
          Tomcat
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/tools/tomcat/" class="nav-link">
  初识
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="English" class="dropdown-title"><span class="title">English</span> <span class="arrow down"></span></button> <button type="button" aria-label="English" class="mobile-dropdown-title"><span class="title">English</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          英语读音
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/english/pronunciation/phonogram.html" class="nav-link">
  音标
</a></li></ul></li><li class="dropdown-item"><h4>
          英语单词
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/english/word/call.html" class="nav-link">
  电话
</a></li><li class="dropdown-subitem"><a href="/english/word/daily-life.html" class="nav-link">
  日常生活
</a></li><li class="dropdown-subitem"><a href="/english/word/animal.html" class="nav-link">
  动物
</a></li></ul></li><li class="dropdown-item"><h4>
          英语语法
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/english/grammar/sentence.html" class="nav-link">
  句子成分
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Study" class="dropdown-title"><span class="title">Study</span> <span class="arrow down"></span></button> <button type="button" aria-label="Study" class="mobile-dropdown-title"><span class="title">Study</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/study/computers/" class="nav-link">
  计算机基础
</a></li><li class="dropdown-item"><!----> <a href="/study/web/" class="nav-link">
  前端知识路线
</a></li><li class="dropdown-item"><!----> <a href="/study/java/" class="nav-link">
  Java知识路线
</a></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Self" class="dropdown-title"><span class="title">Self</span> <span class="arrow down"></span></button> <button type="button" aria-label="Self" class="mobile-dropdown-title"><span class="title">Self</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/self/work/" class="nav-link">
  工作
</a></li></ul></div> <!----></div> <!----></nav> <div class="loginItem"><!----></div></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><!----> <a href="/" class="nav-link">
  首页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="导航" class="dropdown-title"><span class="title">导航</span> <span class="arrow down"></span></button> <button type="button" aria-label="导航" class="mobile-dropdown-title"><span class="title">导航</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/nav/nav.html" class="nav-link">
  常用站点
</a></li><li class="dropdown-item"><!----> <a href="/nav/web.html" class="nav-link">
  前端站点
</a></li><li class="dropdown-item"><!----> <a href="/nav/afterEnd.html" class="nav-link">
  后端站点
</a></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端" class="dropdown-title"><span class="title">前端</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端" class="mobile-dropdown-title"><span class="title">前端</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          CSS+HTML系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/web/csshtml/css-formatContent.html" class="nav-link">
  CSS格式化上下文
</a></li><li class="dropdown-subitem"><a href="/web/csshtml/css-bfc.html" class="nav-link">
  CSS的BFC
</a></li></ul></li><li class="dropdown-item"><h4>
          JS系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/web/js/js-prototype.html" class="nav-link">
  JS-原型与原型链
</a></li><li class="dropdown-subitem"><a href="/web/js/js-context.html" class="nav-link">
  JS-执行上下文
</a></li></ul></li><li class="dropdown-item"><h4>
          Vue2系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/web/vue/mvvm.html" class="nav-link">
  Vue响应式
</a></li></ul></li><li class="dropdown-item"><h4>
          常见面试题
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/web/question/css.html" class="nav-link">
  CSS面试题
</a></li><li class="dropdown-subitem"><a href="/web/question/vue.html" class="nav-link">
  Vue2.x面试题
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Java" class="dropdown-title"><span class="title">Java</span> <span class="arrow down"></span></button> <button type="button" aria-label="Java" class="mobile-dropdown-title"><span class="title">Java</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          基础系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/basics/know.html" class="nav-link">
  Java初识
</a></li><li class="dropdown-subitem"><a href="/java/basics/number.html" class="nav-link">
  Java数字
</a></li><li class="dropdown-subitem"><a href="/java/basics/string.html" class="nav-link">
  Java字符串
</a></li></ul></li><li class="dropdown-item"><h4>
          集合
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/collection/collection.html" class="nav-link">
  Collection集合
</a></li><li class="dropdown-subitem"><a href="/java/collection/list.html" class="nav-link">
  List集合
</a></li></ul></li><li class="dropdown-item"><h4>
          IO操作
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/io/" class="nav-link">
  IO初识
</a></li></ul></li><li class="dropdown-item"><h4>
          网络编程
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/network/ip.html" class="nav-link">
  IP操作
</a></li></ul></li><li class="dropdown-item"><h4>
          JDBC操作
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/java/jdbc/mysql-connect.html" class="nav-link">
  MySQL操作
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="数据库" class="dropdown-title"><span class="title">数据库</span> <span class="arrow down"></span></button> <button type="button" aria-label="数据库" class="mobile-dropdown-title"><span class="title">数据库</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          MySQL系列
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/database/mysql/init.html" class="nav-link">
  常用语法
</a></li><li class="dropdown-subitem"><a href="/database/mysql/data-type.html" class="nav-link">
  数据类型
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="设计模式" class="dropdown-title"><span class="title">设计模式</span> <span class="arrow down"></span></button> <button type="button" aria-label="设计模式" class="mobile-dropdown-title"><span class="title">设计模式</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/designMode/observer.html" aria-current="page" class="nav-link router-link-exact-active router-link-active">
  观察者模式
</a></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="运维/工具" class="dropdown-title"><span class="title">运维/工具</span> <span class="arrow down"></span></button> <button type="button" aria-label="运维/工具" class="mobile-dropdown-title"><span class="title">运维/工具</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Maven
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/tools/maven/" class="nav-link">
  初识
</a></li></ul></li><li class="dropdown-item"><h4>
          Tomcat
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/tools/tomcat/" class="nav-link">
  初识
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="English" class="dropdown-title"><span class="title">English</span> <span class="arrow down"></span></button> <button type="button" aria-label="English" class="mobile-dropdown-title"><span class="title">English</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          英语读音
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/english/pronunciation/phonogram.html" class="nav-link">
  音标
</a></li></ul></li><li class="dropdown-item"><h4>
          英语单词
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/english/word/call.html" class="nav-link">
  电话
</a></li><li class="dropdown-subitem"><a href="/english/word/daily-life.html" class="nav-link">
  日常生活
</a></li><li class="dropdown-subitem"><a href="/english/word/animal.html" class="nav-link">
  动物
</a></li></ul></li><li class="dropdown-item"><h4>
          英语语法
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/english/grammar/sentence.html" class="nav-link">
  句子成分
</a></li></ul></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Study" class="dropdown-title"><span class="title">Study</span> <span class="arrow down"></span></button> <button type="button" aria-label="Study" class="mobile-dropdown-title"><span class="title">Study</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/study/computers/" class="nav-link">
  计算机基础
</a></li><li class="dropdown-item"><!----> <a href="/study/web/" class="nav-link">
  前端知识路线
</a></li><li class="dropdown-item"><!----> <a href="/study/java/" class="nav-link">
  Java知识路线
</a></li></ul></div> <!----></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Self" class="dropdown-title"><span class="title">Self</span> <span class="arrow down"></span></button> <button type="button" aria-label="Self" class="mobile-dropdown-title"><span class="title">Self</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/self/work/" class="nav-link">
  工作
</a></li></ul></div> <!----></div> <!----></nav>  <ul class="sidebar-links"><li><a href="/designMode/observer.html" aria-current="page" class="active sidebar-link">设计模式-观察者模式</a></li></ul> </aside> <main class="page"> <div class="main"><div class="content"><div class="theme-default-content content__default"><h1 id="设计模式-观察者模式"><a href="#设计模式-观察者模式" class="header-anchor">#</a> 设计模式-观察者模式</h1> <p></p><div class="table-of-contents"><ul><li><a href="#概念">概念</a><ul><li><a href="#结构">结构</a></li><li><a href="#优缺点">优缺点</a></li></ul></li><li><a href="#场景">场景</a></li><li><a href="#实现">实现</a><ul><li><a href="#js实现方式">JS实现方式</a></li></ul></li><li><a href="#关于发布订阅者">关于发布订阅者</a><ul><li><a href="#实现">实现</a></li></ul></li></ul></div><p></p> <p>🐴</p> <h2 id="概念"><a href="#概念" class="header-anchor">#</a> 概念</h2> <p><code>观察者模式</code>定义了一种<code>一对多</code>的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都得到通知并被自动更新。</p> <h3 id="结构"><a href="#结构" class="header-anchor">#</a> 结构</h3> <ul><li>观察者<code>Observer</code></li> <li>被观察者<code>Subject</code></li></ul> <div class="imageWrapper" data-v-a88366f6><div class="image" data-v-a88366f6><img src="img/designMode/observe1.png" alt width="500" data-v-a88366f6></div> <!----> <div class="imgModel" style="display:none;" data-v-a88366f6><img src="img/designMode/observe1.png" class="scaleImg" data-v-a88366f6></div></div> <h3 id="优缺点"><a href="#优缺点" class="header-anchor">#</a> 优缺点</h3> <p><strong>优点</strong></p> <ul><li>降低了目标与观察者之间的耦合关系，两者之间是抽象耦合关系。符合依赖倒置原则。</li> <li>支持简单的广播通信，自动通知所有已经订阅过的对象。</li> <li>目标与观察者之间建立了一套触发机制。（页面载入后目标对象很容易与观察者存在一种动态关联，增加了灵活性。）</li></ul> <p><strong>缺点</strong></p> <ul><li>如果一个被观察者对象有很多的直接和间接的观察者的话，将所有的观察者都通知到会花费很多时间。</li> <li>如果在观察者和观察目标之间有循环依赖的话，观察目标会触发它们之间进行循环调用，可能导致系统崩溃。</li> <li>观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的，而仅仅只是知道观察目标发生了变化。</li></ul> <h2 id="场景"><a href="#场景" class="header-anchor">#</a> 场景</h2> <p>比如我们在某宝买东西（比如苹果，香蕉），但是淘宝没有货了。我们可以订阅东西到货时，短信提醒我们，这样不用我们经常关注是否有货。我们不需要该物品时时也可以取消订阅。对于商家而言， 订阅的人可能很多。</p> <p>下面我们来实现该功能：</p> <h2 id="实现"><a href="#实现" class="header-anchor">#</a> 实现</h2> <p>在实现前，根据上面的场景我们可以确定下面这些信息</p> <ul><li>设计一个观察者工具<code>Observer</code>(客户)</li> <li>设计一个被观察者<code>Subject</code>(商家)</li> <li>该工具类有一个订阅方法<code>on</code></li> <li>该工具类有一个发布事件<code>emit</code></li> <li>该工具类有一个取消订阅的方法<code>off</code></li></ul> <h3 id="js实现方式"><a href="#js实现方式" class="header-anchor">#</a> JS实现方式</h3> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">/**
  * @msg 某宝 被观察者
  */</span>
<span class="token keyword">class</span> <span class="token class-name">Subject</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token comment">// 观察者列表</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>observers <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">add</span><span class="token punctuation">(</span><span class="token parameter">obs</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// 添加观察者</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>observers<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>obs<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">remove</span><span class="token punctuation">(</span><span class="token parameter">obs</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// 移除观察者</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>observers <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>observers<span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token parameter">item</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>item <span class="token operator">!==</span> obs<span class="token punctuation">)</span><span class="token punctuation">{</span>
          <span class="token keyword">return</span> item<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
  <span class="token function">notify</span><span class="token punctuation">(</span><span class="token parameter">msg</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// 通知</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>observers<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">obs</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span>
      obs<span class="token punctuation">.</span><span class="token function">receiveNotice</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
 * @msg 客户 观察者
 */</span>
<span class="token keyword">class</span> <span class="token class-name">Observer</span><span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name
  <span class="token punctuation">}</span>
  <span class="token function">receiveNotice</span><span class="token punctuation">(</span><span class="token parameter">msg</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">收到消息：</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>msg<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>


<span class="token comment">//****** 练习 ************* </span>
<span class="token keyword">const</span> LaoWang <span class="token operator">=</span> <span class="token keyword">new</span>  <span class="token class-name">Observer</span><span class="token punctuation">(</span><span class="token string">&quot;老王&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> XiaoMing <span class="token operator">=</span> <span class="token keyword">new</span>  <span class="token class-name">Observer</span><span class="token punctuation">(</span><span class="token string">&quot;小明&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> Bao <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Subject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 订阅</span>
Bao<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>LaoWang<span class="token punctuation">)</span><span class="token punctuation">;</span>
Bao<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>XiaoMing<span class="token punctuation">)</span><span class="token punctuation">;</span>
Bao<span class="token punctuation">.</span><span class="token function">notify</span><span class="token punctuation">(</span><span class="token string">&quot;苹果到了&quot;</span><span class="token punctuation">)</span>

<span class="token comment">// 移除订阅</span>
Bao<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span>LaoWang<span class="token punctuation">)</span><span class="token punctuation">;</span>
Bao<span class="token punctuation">.</span><span class="token function">notify</span><span class="token punctuation">(</span><span class="token string">&quot;手机到了&quot;</span><span class="token punctuation">)</span>
</code></pre></div><h2 id="关于发布订阅者"><a href="#关于发布订阅者" class="header-anchor">#</a> 关于发布订阅者</h2> <p>发布订阅者和观察者模式很相似，很文章也经常说发布订阅者其实就是观察者模式，当然也有文章说两者完全不一样。我们这里不讨论他们的对与错。</p> <p><code>观察者模式</code> 和  <code>发布订阅者</code>还是有些区别。我们来通过它们的结构来探究一下区别：</p> <div class="imageWrapper" data-v-a88366f6><div class="image" data-v-a88366f6><img src="img/designMode/observe1.png" alt width="400" data-v-a88366f6></div> <div class="title" data-v-a88366f6>观察者模式</div> <div class="imgModel" style="display:none;" data-v-a88366f6><img src="img/designMode/observe1.png" class="scaleImg" data-v-a88366f6></div></div> <div class="imageWrapper" data-v-a88366f6><div class="image" data-v-a88366f6><img src="img/designMode/observe2.png" alt width="400" data-v-a88366f6></div> <div class="title" data-v-a88366f6>发布订阅者</div> <div class="imgModel" style="display:none;" data-v-a88366f6><img src="img/designMode/observe2.png" class="scaleImg" data-v-a88366f6></div></div> <p>从上图我们可以很清晰的看到 <code>发布订阅者</code> 可以看出下面区别：</p> <ul><li><code>发布订阅者</code>中多了一个<strong>调度中心</strong>。</li> <li><code>发布订阅者</code>中事件的发布不会直接通知订阅者，而是通过调度中心来作为中间件来通知订阅者。发布者只关心自己信息的发布。</li></ul> <p>可以看出<code>发布订阅者</code>将 <code>观察者</code> 与 <code>订阅者</code>进行了解耦。增强了<code>观察者模式</code>。那<code>发布订阅者</code>到底是不是<code>观察者模式</code>我无法确定。但是确定的是，它们有部分区别。</p> <h3 id="实现-2"><a href="#实现-2" class="header-anchor">#</a> 实现</h3> <p>在现实生活中，我们看到过这样的情景：作者写连载小说时，将自己的书拿到出版社来进行发布，然后很多读者看到后很喜欢，就会从出版社订阅该书。当作者更新小说时，就会发给出版社，然后出版社就会通知读者有更新。这是读者就获取到了连载消息。 这里的<strong>出版社</strong>就充当着调度中心得角色。</p> <p>在实现前，根据上面的场景我们可以确定下面这些信息</p> <ul><li>作家类<code>Writer</code>, 做家具有连载通知方法 <code>publish</code></li> <li>出版社<code>Press</code>, 出版社会有接收做家书籍得方法<code>getBook</code>,订阅方法<code>on</code>, 通知读者发布了小说方法<code>emit</code>，取消订阅小说得方法<code>off</code></li> <li>读者类 <code>Reader</code>,有个一个接收信息得方法<code>receiveMsg</code></li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">/**
 * @msg 作家类
 */</span>
<span class="token keyword">class</span> <span class="token class-name">Writer</span><span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span>book<span class="token punctuation">,</span>press</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>Press <span class="token operator">=</span> press<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>book <span class="token operator">=</span> book<span class="token punctuation">;</span>
    press<span class="token punctuation">.</span><span class="token function">getBook</span><span class="token punctuation">(</span>book<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">publish</span><span class="token punctuation">(</span><span class="token parameter">msg</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// 发布连载小数</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>Press<span class="token punctuation">.</span><span class="token function">emit</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>book<span class="token punctuation">,</span>msg<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
 * @msg 出版社类
 */</span>
<span class="token keyword">class</span> <span class="token class-name">Press</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token comment">// 存储书籍</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>handles <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token comment">/**
   *@msg 接收做家书籍
   */</span>
  <span class="token function">getBook</span><span class="token punctuation">(</span><span class="token parameter">bookName</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>handles<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>bookName<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>handles<span class="token punctuation">[</span>bookName<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
  <span class="token comment">/**
   * @msg 订阅事件
   * @param {事件名称} bookName
   * @param {订阅者} subject
   **/</span> 
  <span class="token function">on</span><span class="token punctuation">(</span><span class="token parameter">bookName<span class="token punctuation">,</span>subject</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token comment">// 判断是否已经存在该事件</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>handles<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>bookName<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
      <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">&quot;所订书籍不存在&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>handles<span class="token punctuation">[</span>bookName<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>subject<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token comment">/**
   * @msg 发布事件
   * @param {事件名称} bookName
   * @param {通知时的参数} args
   */</span>
  <span class="token function">emit</span><span class="token punctuation">(</span><span class="token parameter">bookName<span class="token punctuation">,</span><span class="token operator">...</span>args</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">const</span> handles <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>handles<span class="token punctuation">[</span>bookName<span class="token punctuation">]</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span><span class="token punctuation">(</span>handles<span class="token punctuation">)</span><span class="token punctuation">{</span>
      handles<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">item</span><span class="token punctuation">)</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span>
        item<span class="token punctuation">.</span><span class="token function">receiveMsg</span><span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span>
      <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>bookName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> 该事件未注册</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token comment">/**
   * @msg 删除事件
   * @param {事件名称} bookName
   * @param {原订阅者} subject
   */</span>
  <span class="token function">off</span><span class="token punctuation">(</span><span class="token parameter">bookName<span class="token punctuation">,</span>subject</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>handles<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>bookName<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

      <span class="token comment">// 遍历移除该subject订阅者</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>handles<span class="token punctuation">[</span>bookName<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">item<span class="token punctuation">,</span>index</span><span class="token punctuation">)</span><span class="token operator">=&gt;</span><span class="token punctuation">{</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>item <span class="token operator">===</span> subject<span class="token punctuation">)</span><span class="token punctuation">{</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span>handles<span class="token punctuation">[</span>bookName<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">splice</span><span class="token punctuation">(</span>index<span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span>
      <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>bookName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> 该事件未注册</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">/**
 * @msg 订阅者
 */</span>
<span class="token keyword">class</span> <span class="token class-name">Reader</span><span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">receiveMsg</span><span class="token punctuation">(</span><span class="token parameter">msg</span><span class="token punctuation">)</span><span class="token punctuation">{</span> <span class="token comment">// 接收信息</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> 接收到得信息</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span>msg<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>下面是使用方式</p> <div class="language-java extra-class"><pre class="language-java"><code><span class="token comment">//*************** 使用 *********************</span>
<span class="token keyword">const</span> pre <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Press</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建出版社</span>
<span class="token keyword">const</span> wirter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Writer</span><span class="token punctuation">(</span><span class="token string">&quot;作者名&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;bookOne&quot;</span><span class="token punctuation">,</span>pre<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建作者</span>

<span class="token comment">// 添加订阅者</span>
<span class="token keyword">const</span> <span class="token class-name">ReadcerOne</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Reader</span><span class="token punctuation">(</span><span class="token string">&quot;读者一&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token class-name">ReaderTwo</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Reader</span><span class="token punctuation">(</span><span class="token string">&quot;读者二&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

pre<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">&quot;bookOne&quot;</span><span class="token punctuation">,</span><span class="token class-name">ReadcerOne</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
pre<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">&quot;bookOne&quot;</span><span class="token punctuation">,</span><span class="token class-name">ReaderTwo</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 作者连载，通知</span>
<span class="token comment">/**
 * 读者一 接收到得信息 连载新小说
 * 读者二 接收到得信息 连载新小说
 */</span>
wirter<span class="token punctuation">.</span><span class="token function">publish</span><span class="token punctuation">(</span><span class="token string">&quot;连载新小说&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 删除 bookOne 订阅得 读者一</span>
pre<span class="token punctuation">.</span><span class="token function">off</span><span class="token punctuation">(</span><span class="token string">&quot;bookOne&quot;</span><span class="token punctuation">,</span><span class="token class-name">ReadcerOne</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 作者又连载了，通知</span>
<span class="token comment">/**
 * 读者二 接收到得信息  第二次连载
 */</span>
wirter<span class="token punctuation">.</span><span class="token function">publish</span><span class="token punctuation">(</span><span class="token string">&quot;第二次连载&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p><strong>参考文献</strong></p> <ul><li><a href="http://c.biancheng.net/view/1390.html" target="_blank" rel="noopener noreferrer">观察者模式（Observer模式）详解<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://www.runoob.com/design-pattern/observer-pattern.html" target="_blank" rel="noopener noreferrer">观察者模式<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://www.cnblogs.com/TomXu/archive/2012/03/02/2355128.html" target="_blank" rel="noopener noreferrer">深入理解JavaScript系列（32）：设计模式之观察者模式<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://www.cnblogs.com/minigrasshopper/p/9134196.html" target="_blank" rel="noopener noreferrer">JS设计模式——观察者模式（通俗易懂）<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">最近更新时间:</span> <span class="time">7/2/2021, 11:27:27 AM</span></div></footer> <!----></div> <div class="floatSilder hidden-sm-and-down"><div class="floatSilderWrapper" data-v-4100c7a9><div class="topTitle" data-v-4100c7a9>设计模式-观察者模式</div> <div class="contentNav" data-v-4100c7a9><ul class="nav" data-v-4100c7a9><li class="title" data-v-4100c7a9><a href="#概念" data-v-4100c7a9>概念</a></li><li class="subTitle" data-v-4100c7a9><a href="#结构" data-v-4100c7a9>结构</a></li><li class="subTitle" data-v-4100c7a9><a href="#优缺点" data-v-4100c7a9>优缺点</a></li><li class="title" data-v-4100c7a9><a href="#场景" data-v-4100c7a9>场景</a></li><li class="title" data-v-4100c7a9><a href="#实现" data-v-4100c7a9>实现</a></li><li class="subTitle" data-v-4100c7a9><a href="#js实现方式" data-v-4100c7a9>JS实现方式</a></li><li class="title" data-v-4100c7a9><a href="#关于发布订阅者" data-v-4100c7a9>关于发布订阅者</a></li><li class="subTitle" data-v-4100c7a9><a href="#实现-2" data-v-4100c7a9>实现</a></li></ul></div></div></div></div> </main></div></div><div class="global-ui"><!----></div></div>
    <script src="/assets/js/app.f1a8d465.js" defer></script><script src="/assets/js/2.5bab2b7d.js" defer></script><script src="/assets/js/19.9d056309.js" defer></script><script src="/assets/js/4.dca68745.js" defer></script>
  </body>
</html>
